package com.neusoft.common.db;

import org.springframework.core.*;
import org.springframework.jdbc.core.*;
import org.springframework.jdbc.support.*;

import com.neusoft.common.util.*;


import java.sql.*;
import java.util.*;

public class EncodingColumnMapRowMapper implements RowMapper{
    @SuppressWarnings("unchecked")
    public Object mapRow(ResultSet rs, int rowNum) throws SQLException{
        ResultSetMetaData rsmd = rs.getMetaData();
        int columnCount = rsmd.getColumnCount();
        Map mapOfColValues = createColumnMap(columnCount);
        for(int i = 1; i <= columnCount; i++){
            String key = getColumnKey(rsmd.getColumnName(i));
            Object obj = getColumnValue(rs, i);
            if(String.class.isInstance(obj)){
                obj = EncodingConvert.convertTo8859_1(obj.toString());
            }
            mapOfColValues.put(key, obj);
        }
        return mapOfColValues;
    }

    /**
     * Create a Map instance to be used as column map.
     * <p/>
     * By default, a linked case-insensitive Map will be created if possible, else a plain HashMap (see Spring's
     * CollectionFactory).
     *
     * @param columnCount the column count, to be used as initial capacity for the Map
     *
     * @return the new Map instance
     *
     * @see org.springframework.core.CollectionFactory#createLinkedCaseInsensitiveMapIfPossible
     */
    protected Map createColumnMap(int columnCount){
        return CollectionFactory
                .createLinkedCaseInsensitiveMapIfPossible(columnCount);
    }

    /**
     * Determine the key to use for the given column in the column Map.
     *
     * @param columnName the column name as returned by the ResultSet
     *
     * @return the column key to use
     *
     * @see java.sql.ResultSetMetaData#getColumnName
     */
    protected String getColumnKey(String columnName){
        return columnName;
    }

    /**
     * Retrieve a JDBC object value for the specified column.
     * <p/>
     * The default implementation uses the <code>getObject</code> method. Additionally, this implementation includes a
     * "hack" to get around Oracle returning a non standard object for their TIMESTAMP datatype.
     *
     * @param rs    is the ResultSet holding the data
     * @param index is the column index
     *
     * @return the Object returned
     *
     * @see org.springframework.jdbc.support.JdbcUtils#getResultSetValue
     */
    protected Object getColumnValue(ResultSet rs, int index)
            throws SQLException{
        return JdbcUtils.getResultSetValue(rs, index);
    }
}
